package com.pjc.db;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Tuple;

/**
 * REDIS缓存操作类
 * 
 * @author 王畅
 * @since 2015年6月13日
 */
public class RedisDB {

	protected static final Logger log = LoggerFactory.getLogger(RedisDB.class);
	private static RedisDB instance;
	private String HOST = "";
	private int PORT = 6379;
	private String PASSWORD = "jkt";
	private int REDIS_DB_INDEX = 1;
	private static JedisPool jpool = null;
	private static int CACHE_TIME = 60;

	public static RedisDB getInstance() {
		synchronized (RedisDB.class) {
			if (instance == null)
				instance = new RedisDB();
		}
		return instance;
	}

	/*	*//**
	 * 实列化连接池
	 * 
	 * @param host
	 * @param port
	 * @param dbIndex
	 */
	public void init(String host, int port, int dbIndex) {
		this.HOST = host;
		this.PORT = port;
		this.REDIS_DB_INDEX = dbIndex;
		log.info("初始化Redis连接  HOST={} PORT={} MaxActive=300", this.HOST, Integer.valueOf(this.PORT));
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxActive(600);
		jedisPoolConfig.setMaxIdle(30);
		jedisPoolConfig.setMaxWait(10000L);
		jedisPoolConfig.setTestOnBorrow(true);
		jpool = new JedisPool(jedisPoolConfig, this.HOST, this.PORT);
	}

	/**
	 * 实列化连接池
	 * 
	 * @param host
	 * @param port
	 * @param dbIndex
	 * @param maxActive
	 * @param maxIdle
	 */
	public void init(String host, int port, int dbIndex, int maxActive, int maxIdle) {
		this.HOST = host;
		this.PORT = port;
		this.REDIS_DB_INDEX = dbIndex;
		log.info("初始化Redis连接  HOST={} PORT={} MaxActive={}", new Object[] { this.HOST, Integer.valueOf(this.PORT), Integer.valueOf(maxActive) });
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxActive(maxActive);
		jedisPoolConfig.setMaxIdle(maxIdle);
		jedisPoolConfig.setMaxWait(10000L);
		jedisPoolConfig.setTestOnBorrow(true);
		jpool = new JedisPool(jedisPoolConfig, this.HOST, this.PORT);
	}

	/**
	 * 实列化连接池
	 * 
	 * @param host
	 * @param port
	 * @param dbIndex
	 */
	public void init(String host, int port, String pwd, int dbIndex) {
		this.HOST = host;
		this.PORT = port;
		this.PASSWORD = pwd;
		this.REDIS_DB_INDEX = dbIndex;
		log.info("初始化Redis连接  HOST={} PORT={} MaxActive=300", this.HOST, Integer.valueOf(this.PORT));
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxActive(600);
		jedisPoolConfig.setMaxIdle(30);
		jedisPoolConfig.setMaxWait(10000L);
		jedisPoolConfig.setTestOnBorrow(true);
		jpool = new JedisPool(jedisPoolConfig, this.HOST, this.PORT, 2000, this.PASSWORD);
	}

	/**
	 * 实列化连接池
	 * 
	 * @param host
	 * @param port
	 * @param dbIndex
	 * @param maxActive
	 * @param maxIdle
	 */
	public void init(String host, int port, String pwd, int dbIndex, int maxActive, int maxIdle) {
		this.HOST = host;
		this.PORT = port;
		this.PASSWORD = pwd;
		this.REDIS_DB_INDEX = dbIndex;
		log.info("初始化Redis连接  HOST={} PORT={} MaxActive={}", new Object[] { this.HOST, Integer.valueOf(this.PORT), Integer.valueOf(maxActive) });
		JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
		jedisPoolConfig.setMaxActive(maxActive);
		jedisPoolConfig.setMaxIdle(maxIdle);
		jedisPoolConfig.setMaxWait(10000L);
		jedisPoolConfig.setTestOnBorrow(true);
		jpool = new JedisPool(jedisPoolConfig, this.HOST, this.PORT, 2000, this.PASSWORD);
	}

	/**
	 * 根据key获取val值(string类型)
	 * 
	 * @param key
	 * @return
	 */
	public String get(String key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.get(key);
		} catch (Exception e) {
			log.error("RedisDB get error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	/**
	 * 根据key获取val值(byte[]类型)
	 * 
	 * @param key
	 * @return
	 */
	public byte[] get(byte[] key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.get(key);
		} catch (Exception e) {
			log.error("RedisDB get error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	/**
	 * 判断key是否存在
	 * 
	 * @param userID
	 * @return
	 */
	public boolean exist(String userID) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.exists(userID).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB exist error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	/**
	 * 添加健值队到redis中(默认60秒失效)
	 * 
	 * @param userID
	 * @param val
	 */
	public void add(String userID, String val) {
		add(userID, val, CACHE_TIME);
	}

	/**
	 * 添加健值队到redis中
	 * 
	 * @param userID
	 * @param val
	 * @param seconds
	 */
	public void add(String userID, String val, int seconds) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.set(userID, val);
			jedis.expire(userID, seconds);
		} catch (Exception e) {
			log.error("RedisDB add error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public boolean existsZSet(String key, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			return jedis.exists(key).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB existsZSet error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public void addZSet(String key, double k, String member, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			jedis.zadd(key, k, member);
		} catch (Exception e) {
			log.error("RedisDB addZSet error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void addIncr(String key, double k, String member, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			jedis.zincrby(key, k, member);
		} catch (Exception e) {
			log.error("RedisDB addIncr error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public Set<Tuple> getZSortSet(String key, int start, int end, boolean desc, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			if (desc) {
				return jedis.zrevrangeWithScores(key, start, end);
			}
			return jedis.zrangeWithScores(key, start, end);
		} catch (Exception e) {
			log.error("RedisDB getZSortSet error" + e.getMessage(), e);
		} finally {
			if (jedis != null) {
				jpool.returnResource(jedis);
			}
		}
		return null;
	}

	public boolean isExistsKey(String key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.exists(key).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB isExistsKey error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public boolean isExistsKey(byte[] key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.exists(key).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB isExistsKey error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public boolean isExistsKey(byte[] key, byte[] field) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.hexists(key, field).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB isExistsKey error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public void setData(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.set(key, value);
		} catch (Exception e) {
			log.error("RedisDB setData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void setData(byte[] key, byte[] value) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.set(key, value);
		} catch (Exception e) {
			log.error("RedisDB setData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void setData(byte[] key, byte[] value, int expireTime) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.set(key, value);
			jedis.expire(key, expireTime);
		} catch (Exception e) {
			log.error("RedisDB setData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public long setIncreData(String key, int incr, int expire) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			long l = jedis.incrBy(key, expire).longValue();
			if (expire != -1) {
				jedis.expire(key, expire);
			}
			return l;
		} catch (Exception e) {
			log.error("RedisDB setIncreData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return -1;
	}

	public byte[] getData(byte[] keys) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.get(keys);
		} catch (Exception e) {
			log.error("RedisDB getData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public String getData(String key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.get(key);
		} catch (Exception e) {
			log.error("RedisDB getData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public void setHashData(byte[] key, byte[] field, byte[] value) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.hset(key, field, value);
		} catch (Exception e) {
			log.error("RedisDB setHashData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void delKey(byte[] key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.del(new byte[][] { key });
		} catch (Exception e) {
			log.error("RedisDB delKey error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public List<byte[]> getHashDataAll(byte[] key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.hvals(key);
		} catch (Exception e) {
			log.error("RedisDB getHashDataAll error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public byte[] getHashData(byte[] key, byte[] field) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.hget(key, field);
		} catch (Exception e) {
			log.error("RedisDB getHashData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public boolean hexists(byte[] key, byte[] field) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.hexists(key, field).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB hexists error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public boolean hexists(String key, String field) throws Exception {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.hexists(key, field).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB hexists error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

	public Map<byte[], byte[]> getHashData(byte[] key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);

			if (!jedis.exists(key).booleanValue()) {
				return null;
			}
			return jedis.hgetAll(key);
		} catch (Exception e) {
			log.error("RedisDB getHashData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public void delHashData(byte[] key, byte[] field) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.hdel(key, new byte[][] { field });
		} catch (Exception e) {
			log.error("RedisDB delHashData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public List<byte[]> getListData(byte[] key, int start, int end) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.lrange(key, start, end);
		} catch (Exception e) {
			log.error("RedisDB getListData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public void putListData(byte[] key, byte[][] vals) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.lpush(key, vals);
		} catch (Exception e) {
			log.error("RedisDB putListData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void delListData(byte[] key, byte[] val) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.lrem(key, 1, val);
		} catch (Exception e) {
			log.error("RedisDB delListData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void setExpire(byte[] key, int seconds) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			jedis.expire(key, seconds);
		} catch (Exception e) {
			log.error("RedisDB setExpire error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public void saveZSet(String key, Set<Tuple> maps, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			if ((maps == null) || (maps.size() <= 0))
				return;
			double i = 1.0D;
			for (Tuple t : maps)
				jedis.zadd(key, i - 0.0001D, t.getElement());
		} catch (Exception e) {
			log.error("RedisDB saveZSet error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
	}

	public Set<Tuple> getZSortSet(String key, int start, int end, boolean desc, boolean clear, int dbIndex) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(dbIndex);
			if (desc) {
				return jedis.zrevrangeWithScores(key, start, end);
			}
			return jedis.zrangeWithScores(key, start, end);
		} catch (Exception e) {
			log.error("RedisDB getZSortSet error" + e.getMessage(), e);
		} finally {
			if (jedis != null) {
				if (clear) {
					jedis.zremrangeByRank(key, 0L, -1L);
				}
				jpool.returnResource(jedis);
			}
		}
		return null;
	}

	public Set<String> getSetData(String key) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.smembers(key);
		} catch (Exception e) {
			log.error("RedisDB getSetData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return null;
	}

	public long putSetData(String key, String[] members) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.sadd(key, members).longValue();
		} catch (Exception e) {
			log.error("RedisDB putSetData error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return -1;
	}

	public boolean sismenber(String key, String member) {
		Jedis jedis = null;
		try {
			jedis = (Jedis) jpool.getResource();
			jedis.select(this.REDIS_DB_INDEX);
			return jedis.sismember(key, member).booleanValue();
		} catch (Exception e) {
			log.error("RedisDB sismenber error" + e.getMessage(), e);
		} finally {
			if (jedis != null)
				jpool.returnResource(jedis);
		}
		return false;
	}

}
